package trucaso;
/*
 * Class to create a server and play online (it's not a dedicated server, you use it to play)
 */

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;

import javax.swing.JOptionPane;

public class Server extends Game implements Runnable {
	protected ChatPane chatPane;
	protected ServerSocket server = null;
	protected int port;
	protected Thread serverThread;
	protected int serverScore,clientScore;
	protected int envidoValue,trucoValue;
	protected int cardsPlayed;
	
	protected Server(Deck d, CardZone c,Actions a,ScoreBoard sb,ChatPane cp, int p) {
		super(d,c,a,sb,cp);
		port = p;
		chatPane = cp;
		turn = true;
		resetScores();
		
		actions.maso.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent evt) {
				maso();
				finishGame(name2);
			}
		});
		
		name = "Server";
		name2 = "Client";
		cp.putMessage("Starting a new Server...");
		serverThread = new Thread(this);
		serverThread.start();
		
	}
	
	public void run() {
		cardZone.repaint();
		try{  
			chatPane.putMessage("Binding to port " + port + ", please wait  ...");
	        server = new ServerSocket(port);  
	        chatPane.putMessage("Server started: " + server);
	        scores.setNames(name,name2);
	        String ipAddr = InetAddress.getLocalHost().getHostAddress();
	        chatPane.putMessage("Tell your friends to connect to "+ipAddr+":"+port);
	        chatPane.putMessage("Waiting for a client ...");
	        socket = server.accept();
	        chatPane.putMessage("Client accepted: " + socket);
			try{
				open();
			}catch(IOException ioex) {
				chatPane.putMessage(ioex.getMessage());
			}
			sendVersion();
			getCards();
	        sendBothHands();
	        actions.resetButtons();
	        cardZone.setCards();
	        cardZone.repaint();
		}catch(IOException eioi) {
			chatPane.putMessage("Binding Error! "+eioi.getMessage());
		}
		
		chatPane.setOutputStream(streamOut);

        while(true){
        	try{  
        		String line = streamIn.readUTF();
           	  	if(line.length()>0) {
           	  		char c = line.charAt(0);
           	  		switch(c) {
           	  		case '<':chatPane.putMessage(line);break;
           	  		case 'p':if(both[Integer.parseInt(line.substring(2))].isInGame()) {
   	  							cardZone.playCard(Integer.parseInt(line.substring(2)),true);
   	  							cardsPlayed++;
   	  							turn=!turn;
   	  						}
   	  						checkStatus();
   	  						break;
           	  		case 'f':checkStatus();break;
           	  		case 'n':receiveName(line);break;
           	  		case 'm':receiveMaso();finishGame(name);cardZone.repaint();break;
           	  		case 'v':checkVersion(line);break;
           	  		default: chatPane.putMessage("Something weird Just Happened...");break;
           	  		}
           	  	}
           }catch(IOException ioe){
        	   chatPane.putMessage(name2+" Disconnected, waiting for clients...");
        	
           		try{
           			close();
           		}catch(IOException iox) {
           			chatPane.putMessage("Error While Closing! "+iox.getMessage());
           		}
           		try {
           			socket = server.accept();
           			chatPane.putMessage("Client accepted: " + socket);
           			try{
           				open();
           				getCards();
           				sendBothHands();
           				cardZone.setCards();
           				cardZone.repaint();
           			}catch(IOException ioex) {
           				chatPane.putMessage(ioex.getMessage());
           			}
           		}catch(IOException iosa) {
           			chatPane.putMessage("Error! "+iosa.getMessage());
           		}
  		
           }
		}
	}
	
	protected void checkStatus() {
		if(cardsPlayed < 2) return;
		if(cardsPlayed%2 != 0) return;
		int s = 0,c = 0;
		if(cardsPlayed==2) {
			if(both[cardZone.getCardOrder()[0]].getValue()<both[cardZone.getCardOrder()[3]].getValue()) {
				turn=false;
				try{
					streamOut.writeUTF("t ");
					streamOut.flush();
				}catch(IOException io) {}
			}else {
				turn=true;
			}
		}
		if(cardsPlayed > 3) {
			if(both[cardZone.getCardOrder()[0]].getValue()<both[cardZone.getCardOrder()[3]].getValue()) {
				s++;
			}else {
				if(both[cardZone.getCardOrder()[0]].getValue()==both[cardZone.getCardOrder()[3]].getValue()) {
					c++;
					s++;
				}else { c++; }
			}
			if(both[cardZone.getCardOrder()[1]].getValue()<both[cardZone.getCardOrder()[4]].getValue()) {
				s++;
			}else {
				if(both[cardZone.getCardOrder()[1]].getValue()==both[cardZone.getCardOrder()[4]].getValue()) {
					c++;
					s++;
				}else { c++; }
			}
			if((c==2)&&(c!=s)) {
				finishGame(name2);
				return;
			}else {
				if((s==2)&&(c!=s)) {
					finishGame(name);
					return;
				}
			}
		}
		if(cardsPlayed == 6) {
			if(both[cardZone.getCardOrder()[2]].getValue()<both[cardZone.getCardOrder()[5]].getValue()) {
				s++;
			}else {
				if(both[cardZone.getCardOrder()[2]].getValue()==both[cardZone.getCardOrder()[5]].getValue()) {
					c++;
					s++;
				}else { c++; }
			}
			if((c==3)&&(c!=s)) {
				finishGame(name2);
			}else {
				if((s==3)&&(c!=s)) {
					finishGame(name);
				}else {
					if(turn) finishGame(name);
					else finishGame(name2);
				}
			}
		}
	}
	
	protected void playCard(int n) {
		try{
			streamOut.writeUTF("p "+n);
			streamOut.flush();
			cardsPlayed++;
			turn=!turn;
		}catch(IOException ioex) {
			chatPane.putMessage("Game Error! You're playing against no one! Panic!");
		}
	}
	
	protected void finishGame(String winner) {
		calculateScores();
		cardsPlayed = 0;
		turn = !turn;
		JOptionPane.showMessageDialog(cardZone,"Game finished, " + winner +
				" wins\nClick OK to deal cards");
		returnCards();
		getCards();
		sendBothHands();
		actions.resetButtons();
		cardZone.repaint();
	}
	
	protected void getCards() {
		for(int i=0;i<6;i++) {
			both[i] = deck.getRandomCard();
			if(i>2) both[i].setVisible(true);
		}
		cardZone.reset();
	}
	
	protected void calculateScores() {
		if(envidoValue>=0) serverScore = serverScore+envidoValue;
		else clientScore = clientScore-envidoValue;
		if(trucoValue>=0) serverScore = serverScore+trucoValue;
		else clientScore = clientScore-trucoValue;
	}
	
	protected void setServerScore(int s) {
		serverScore = s;
	}
	
	protected void setClientScore(int s) {
		clientScore = s;
	}
	
	protected void setScores(int server, int client) {
		serverScore = server;
		clientScore = client;
	}
	
	protected void resetScores() {
		serverScore = 0;
		clientScore = 0;
	}
	
	protected int getServerScore() {
		return serverScore;
	}
	
	protected int getClientScore() {
		return clientScore;
	}
	
	protected void sendScores() {
		String s,c;
		if(serverScore<10) {
			s = "0"+serverScore;
		}else {
			s = Integer.toString(serverScore);
		}
		if(clientScore<10) {
			c = "0"+clientScore;
		}else {
			c = Integer.toString(clientScore);
		}		
		try{
			streamOut.writeUTF("s "+s+c);
			streamOut.flush();
		}catch(IOException ioex) {
			chatPane.putMessage("Error while sending the Scores! ");
		}
	}
	
	
	protected void sendBothHands() {
		StringBuffer hands = new StringBuffer("h ");
		for(int i=0;i<6;i++) {
			if(both[i].getNumber()<10){
				hands.append("0"+both[i].getNumber());
			}else{
				hands.append(both[i].getNumber());
			}
		}
		try{
			streamOut.writeUTF(hands.toString());
			streamOut.flush();
		}catch(IOException ioex) {
			chatPane.putMessage("Error while sending cards data! ");
		}
	}
}
